﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Xml.Linq;
using AzukiMap.Map;
using AzukiMap.MapSource;
using AzukiMap.Renderer;
using AzukiMap.Request;
using GeoAPI.Geometries;

namespace AzukiMap.Layer
{
    public class RasterIndexLayer : MapLayer
    {
        RasterRenderer _renderer;
        private List<RasterIndexRecord> _records;
        List<int> _renderedImages;
        bool _isClockWise = true;

        public bool IsClockWise
        {
            get { return _isClockWise; }
            set { _isClockWise = value; }
        }

        public List<RasterIndexRecord> Records
        {
            get { return _records; }
            set { _records = value; }
        }

        public RasterIndexLayer()
        {

        }

        public RasterIndexLayer(string name)
            : base(MapSourceTypes.Raster, new RasterFileSource())
        {
            _renderer = new RasterRenderer(this);
            Records = new List<RasterIndexRecord>();
            _renderedImages = new List<int>();
            LayerName = name;
        }

        public override void Draw()
        {
            base.Draw();
            // return when not drawable
            if (!IsDrawable)
            {
                return;
            }

            if ((!base.IsRendering && base.IsVisible) && base.CheckScale())
            {
                base.IsRendering = true;
                this.DrawInExtent();
            }
        }

        public override void Redraw()
        {
            Children.Clear();
            base.Redraw();
            //Draw();
        }

        public void AddRaster(RasterIndexRecord record)
        {
            Records.Add(record);
            //Draw();
        }

        public void RemoveRaster(RasterIndexRecord record)
        {
            Records.Remove(record);
            Redraw();
        }

        public void RemoveRasterAll()
        {
            Records.Clear();
            Redraw();
        }

        void DrawInExtent()
        {
            foreach (RasterIndexRecord record in Records)
            {
                if (this._renderedImages.Contains(record.Id))
                {
                    foreach (var image in record.Images)
                    {
                        record.Images.Remove(image);
                        base.Children.Remove(image);
                    }
                    RenderedElements.Remove(record.Id);
                    record.Images.Clear();
                }
            }

            RenderedElements.Clear();

            // TODO: get uniq ID from records.
            foreach (RasterIndexRecord record in Records)
            {
                /*
                if (this._renderedImages.Contains(record.Id))
                {
                    foreach (var image in record.Images)
                    {
                        record.Images.Remove(image);
                        base.Children.Remove(image);
                    }
                    RenderedElements.Remove(record.Id);
                    record.Images.Clear();
                }
                 */

                if (!this._renderedImages.Contains(record.Id) && this.IsOnMapCanvas(record.Extent))
                {
                    foreach (IPolygon area in record.Extent.Geometries)
                    {
                        IList<FrameworkElement> images = this._renderer.Draw(new Uri(record.RasterIndex, UriKind.RelativeOrAbsolute), area);
                        RenderedElements[record.Id] = images;

                        foreach (FrameworkElement img in images)
                        {
                            img.Visibility = record.Visibility;
                            img.SetValue(ZIndexProperty, record.ZIndex);
                            img.Opacity = record.Opacity;

                            base.Children.Add(img);
                            record.Images.Add(img);
                        }
                    }
                }
            }
            IsRendering = false;
        }

        public override XElement ToXml()
        {
            return ToXml("RasterIndexLayer");
        }

        public override XElement ToXml(string elementName)
        {
            XElement vectorLayerXml = base.ToXml(elementName);
            return vectorLayerXml;
        }

        protected bool IsOnMapCanvas(IMultiPolygon extent)
        {
            //bool isInCanvas = this.MapCoord.CurrentExtent.Intersects(extent);
            bool isInCanvas = CurrentExtent.Intersects(extent);
            bool isInMaxExtent = true;
            if (base.MaxExtent != null)
            {
                isInMaxExtent = base.MaxExtent.Intersects(extent);
            }
            return (isInCanvas && isInMaxExtent);
        }
    }
}
